{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Multi-view reconstruction and Meshing\n", "\n", "## 0. Import" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "\n", "import cv2\n", "\n", "import openalea.phenomenal.data as phm_data\n", "import openalea.phenomenal.display as phm_display\n", "import openalea.phenomenal.object as phm_obj\n", "import openalea.phenomenal.multi_view_reconstruction as phm_mvr\n", "import openalea.phenomenal.mesh as phm_mesh\n", "import openalea.phenomenal.display.notebook as phm_display_notebook" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. Prerequisites\n", "\n", "### 1.1 Load data" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plant_number = 2 # Available : 1, 2, 3, 4 or 5\n", "bin_images = phm_data.bin_images(f\"data/plant_{plant_number}\")\n", "calibrations = phm_data.calibrations(f\"data/plant_{plant_number}\")\n", "\n", "phm_display.show_images(\n", " list(bin_images[\"side\"].values()) + list(bin_images[\"top\"].values())\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. Multi-view reconstruction\n", "\n", "### 2.1 Associate images and projection function" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def routine_select_ref_angle(bin_side_images):\n", " max_len = 0\n", " max_angle = None\n", "\n", " for angle in bin_side_images:\n", " x_pos, y_pos, x_len, y_len = cv2.boundingRect(\n", " cv2.findNonZero(bin_side_images[angle])\n", " )\n", "\n", " if x_len > max_len:\n", " max_len = x_len\n", " max_angle = angle\n", "\n", " return max_angle" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "refs_angle_list = [routine_select_ref_angle(bin_images[\"side\"])]\n", "print(refs_angle_list)\n", "\n", "image_views = list()\n", "for id_camera in bin_images:\n", " for angle in bin_images[id_camera]:\n", " projection = calibrations[id_camera].get_projection(angle)\n", "\n", " image_ref = None\n", " if id_camera == \"side\" and angle in refs_angle_list:\n", " image_ref = bin_images[id_camera][angle]\n", "\n", " inclusive = False\n", " if id_camera == \"top\":\n", " inclusive = True\n", "\n", " image_views.append(\n", " phm_obj.ImageView(\n", " bin_images[id_camera][angle],\n", " projection,\n", " inclusive=inclusive,\n", " image_ref=image_ref,\n", " )\n", " )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.2 Do multi-view reconstruction" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "voxels_size = 16 # mm\n", "error_tolerance = 0\n", "voxel_grid = phm_mvr.reconstruction_3d(\n", " image_views, voxels_size=voxels_size, error_tolerance=error_tolerance\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.4 Save / Load voxel grid" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "voxel_grid.write(f\"plant_{plant_number}_size_{voxels_size}.npz\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "voxel_grid = phm_obj.VoxelGrid.read(f\"plant_{plant_number}_size_{voxels_size}.npz\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.5 Viewing" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "phm_display_notebook.show_voxel_grid(voxel_grid, size=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3.Meshing" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "vertices, faces = phm_mesh.meshing(\n", " voxel_grid.to_image_3d(), reduction=0.90, smoothing_iteration=5, verbose=True\n", ")\n", "\n", "print(\"Number of vertices : {nb_vertices}\".format(nb_vertices=len(vertices)))\n", "print(\"Number of faces : {nb_faces}\".format(nb_faces=len(faces)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Viewing" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "phm_display_notebook.show_mesh(vertices, faces)" ] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.7" }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": {}, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 4 }